/*
 * Copyright (c) 2022，公司名称
 * All rights reserved.
 * 文件名称：low_lin.c
 * 摘要：底边LIN
 * 当前版本：V1.0.0,WCD,2023/1/10,初版
 * 历史版本：Vx.x.x，编写者/修改者，修改时间，修改内容（重大发布时，总结重点变更内容）
 */
#include "low_includes.h"

/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓应用层数据定义开始↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
#if 1
static uint32_t u32LinRecTick = 0U;           /* Lin总线活动时间 */
static RLINSTA_E eRlin31Sta = RLINSTA_NORMAL; /* Lin总线运行状态 */
void Update_LIN_sending_data(void);
static void Lin_Tick_Update(void);
#endif
/*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑应用层数据定义结束↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/


/* LIN Error callback */
void (*LIN_Res_Error_Status_callback)(LIN_Res_Error_Status LIN_Error_Status) = NULL;
/*lin respones error status flag LIN响应错误状态标志*/
LIN_Res_Error_Status linErrorStatus;

/**
 *  @brief default LIN master initial configuration 默认LIN主初始配置
 */
static const UART_LinConfig_t slaveCfg =
    {
        19200, 64000000, UART_LIN_SLAVE, DISABLE};

const UART_LinHeader_t uartLinHeader[2] =
    {
        /* 6-bit id                break length     delimeter*/
        Report_Value_ID,
        13,
        1,
        CA_Contrl_ID,
        13,
        1,
};

UART_LinResponse_t uartLinSlaveResponse =
    {
        UART_LIN_CHECKSUM_ENHANCED, // checksum type 校验和类型
        8,                          // len
        {8, 7, 6, 5, 4, 3, 2, 1},   // data
};

UART_LinResponse_t linResponse =
    {
        UART_LIN_CHECKSUM_ENHANCED, // checksum type
        8,                          // len
        {0, 0, 0, 0, 0, 0, 0, 0},   // data
};

/*uart Hardware id uart硬件id*/
uint8_t gChannelId;
/*set timeout time 设置超时时间*/
static uint16_t gResTimeoutTime;
/*timeout time check flag 超时时间检查标志*/
static uint8_t gResTimeoutFlag = 0;

/**
 * @brief      Computes the maximum response timeout 计算最大响应超时
 *              TResponse_Maximum = 1.4 * TResponse_Nominal,
 *                TResponse_Nominal = 10 * (NData+ 1) * TBit
 *
 *
 * @param[in]  baudRate:Lin baudRate  size:DLC
 *
 * @return     ResultStatus_t  send header status
 *
 */
static uint16_t resMaxTimeout(uint32_t baudRate, uint8_t size)
{
    uint16_t timeoutTime;
    timeoutTime = (uint16_t)(14U * (1U + (uint16_t)size));

    return (uint16_t)((timeoutTime * 1000000U / (TIME_OUT_UNIT_US * baudRate)) + 1U);
}

/**
 * @brief  500us time interrupt for LIN task period scheduling 用于LIN任务周期调度的500us时间中断
 *
 * @param  none
 *
 * @return none
 *
 */
void TIME_PeriodHandle(void)
{
    /*500u interrupt*/
    if (1 == gResTimeoutFlag)
    {
        /*response timeout check */
        if (0 == gResTimeoutTime)
        {
            gResTimeoutFlag = 0;
            if (SET == UART_LinGetTransmissionStatus(LIN_SLAVE_ID))
            {
                UART_LinStopTransmission((UART_ID_t)LIN_SLAVE_ID);
            }
            /* 1.Start receiving header(Enable rx) */
            UART_LinStartReceiveHeader((UART_ID_t)LIN_SLAVE_ID);
        }
        else
        {
            gResTimeoutTime--;
        }
    }
    // GPIO_TogglePinOutput(PORT_E, GPIO_11);//反转电平测试时间
}

/**
 * @brief     LIN response done interrupt callback function LIN响应完成中断回调功能
 *
 * @param[in]  void
 *
 * @return     none
 *
 */
/* slave */
void lin_response_finish_callback_slave()
{
    uint32_t id;
    /* check the checksum error and time out error in LIN mode 检查LIN模式下的校验和错误和超时错误*/
    if ((UART_LIN_RSP_ERR_FLAG & UART_GetLineStatusBufForCbf(UART0_ID)) != 0U)
    {
        linErrorStatus = LIN_RSP_DONE_INT_ERR;
        if (NULL != LIN_Res_Error_Status_callback)
        {
            LIN_Res_Error_Status_callback(linErrorStatus);
        }
        else
        {
        }
    }
    else
    {
        id = UART_LinGetId(LIN_SLAVE_ID);
        /*clear check flag 清除检查标志*/
        gResTimeoutFlag = 0;

        switch (id)
        {
        case Report_Value_ID:
            /*Add your own handler 添加您自己的处理程序*/
            break;
        case CA_Contrl_ID:
            /*receive respose data*/
	
            //UART_LinReadResponse(LIN_SLAVE_ID, linResponse.len, linResponse.data);//接受数据
            UART_LinReadResponse(LIN_SLAVE_ID, CA_Contrl.len, CA_Contrl.msg.data);//接受数据
            break;
        default:
            linErrorStatus = LIN_RES_ID_CONFLICT;
            if (NULL != LIN_Res_Error_Status_callback)
            {
                LIN_Res_Error_Status_callback(linErrorStatus);
            }
            else
            {
            }
            break;
        }
    }

    /*set Header receive status 设置头接收状态*/
    if (SET == UART_LinGetTransmissionStatus(LIN_SLAVE_ID))
    {
        UART_LinStopTransmission((UART_ID_t)LIN_SLAVE_ID);
    }
    /* 1.Start receiving header(Enable rx) 1.开始接收头（启用rx）*/
    UART_LinStartReceiveHeader((UART_ID_t)LIN_SLAVE_ID);
}

/**
 * @brief     LIN header done interrupt callback function LIN头完成中断回调功能
 *
 * @param[in]  void
 *
 * @return     none
 *
 */
void lin_header_finish_callback_slave()
{
    uint32_t id_h = 0;
    /* check the sync field error , PID error and timeout error 检查同步字段错误、PID错误和超时错误*/
    if ((UART_LIN_HEADER_ERR_FLAG & UART_GetLineStatusBufForCbf(UART0_ID)) != 0U)
    {
        linErrorStatus = LIN_HEADER_DONE_INT_ERR;
        if (NULL != LIN_Res_Error_Status_callback)
        {
            LIN_Res_Error_Status_callback(linErrorStatus);
        }
        else
        {
        }
        /*set Header receive status 设置头接收状态*/
        if (SET == UART_LinGetTransmissionStatus(LIN_SLAVE_ID))
        {
            UART_LinStopTransmission((UART_ID_t)LIN_SLAVE_ID);
        }
        /* Start receiving header(Enable rx) 开始接收头（启用rx）*/
        UART_LinStartReceiveHeader((UART_ID_t)LIN_SLAVE_ID);
        /*clear check flag*/
        gResTimeoutFlag = 0;
    }
    else
    {
        id_h = UART_LinGetId(LIN_SLAVE_ID);
        switch (id_h)
        {
        case Report_Value_ID:
            /* send response 发送响应*/
						Update_LIN_sending_data();
            UART_LinSendResponse(LIN_SLAVE_ID, &uartLinSlaveResponse);//发送响应数据
            /*set response timeout 设置响应超时*/
            gResTimeoutTime = resMaxTimeout(slaveCfg.baudRate, uartLinSlaveResponse.len);
            /*set check flag 设置检查标志*/
            gResTimeoutFlag = 1;
            break;
        case CA_Contrl_ID:
            /*set receive response 设置接收响应*/
            UART_LinStartReceiveResponse(LIN_SLAVE_ID, linResponse.checkType, linResponse.len);
            /*set response timeout  设置响应超时*/
            gResTimeoutTime = resMaxTimeout(slaveCfg.baudRate, linResponse.len);
            /*set check flag 设置检查标志*/
            gResTimeoutFlag = 1;
            break;
        default:
            /*set Header receive status 设置头接收状态*/
            if (SET == UART_LinGetTransmissionStatus(LIN_SLAVE_ID))
            {
                UART_LinStopTransmission((UART_ID_t)LIN_SLAVE_ID);
            }
            /* 1.Start receiving header(Enable rx) 1.开始接收头（启用rx）*/
            UART_LinStartReceiveHeader((UART_ID_t)LIN_SLAVE_ID);
            /*clear check flag 清除检查标志*/
            gResTimeoutFlag = 0;
            break;
        }
    }
    Lin_Tick_Update();
}

/**
 * @brief  system clock
 *
 * @param  none
 *
 * @return none
 *
 */
void low_lin_clock_init(void)
{
    /* Select uart0 clock */
    CLK_ModuleSrc(CLK_UART0, CLK_SRC_FIRC64M);
    /* Set function clock divider */
    CLK_SetClkDivider(CLK_UART0, CLK_DIV_2);
}

void low_lin_init()
{
    /* Enable module */
    SYSCTRL_EnableModule(SYSCTRL_UART0);

    /* Install callback function */
    UART_InstallCallBackFunc(LIN_SLAVE_ID, UART_INT_HEADER_DONE, lin_header_finish_callback_slave);
    UART_InstallCallBackFunc(LIN_SLAVE_ID, UART_INT_RSP_DONE, lin_response_finish_callback_slave);
    UART_IntMask(LIN_SLAVE_ID, UART_INT_HEADER_DONE, UNMASK);
    UART_IntMask(LIN_SLAVE_ID, UART_INT_RSP_DONE, UNMASK);

    /*When UART re-open after close, need to check and clear busy status*/
    while (ERR == UART_WaitBusyClear(LIN_SLAVE_ID, 7000))
    {
        (void)UART_ReceiveByte(LIN_SLAVE_ID);
    }

    /* Module init */
    UART_LinConfig(LIN_SLAVE_ID, &slaveCfg);
    /* enable IRQ*/
    NVIC_EnableIRQ(UART0_IRQn);

    /* 1.Start receiving header(Enable rx) */
    UART_LinStartReceiveHeader((UART_ID_t)LIN_SLAVE_ID);
}

/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓应用层函数定义开始↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
#if 1

void Update_LIN_sending_data(void)
{
	 uartLinSlaveResponse.checkType = UART_LIN_CHECKSUM_ENHANCED;
   uartLinSlaveResponse.len = RFDL_8_byte_and_checksum;
	 memcpy(uartLinSlaveResponse.data, Report_Value.msg.data, uartLinSlaveResponse.len);
}

/*
 * 函数介绍: 更新总线活动时间
 * 返回值: {*}
 * 备注:
 */
static void Lin_Tick_Update(void)
{
    u32LinRecTick = Get1MsTickVal();
}
/* 
 * 函数介绍: 更新总线状态
 * 参数: {RLINSTA_E} sta
 * 返回值: {*}
 * 备注: 
 */
static void RLIN31_sta_update(RLINSTA_E sta)
{
    eRlin31Sta = sta;
}
/* 
 * 函数介绍: 获取总线状态
 * 参数: {RLINSTA_E} sta
 * 返回值: {*}
 * 备注: 
 */
RLINSTA_E RLIN31_sta_get(void)
{
    return eRlin31Sta;
}
/* 
 * 函数介绍: 唤醒RLIN31
 * 返回值: {*}
 * 备注: 
 */
extern void RLIN31_Wakeup(void)
{
    RLIN31_sta_update(RLINSTA_NORMAL);
    Lin_Tick_Update();
}
/* 
 * 函数介绍: LIN总线状态检测
 * 返回值: {RLINSTA_E}  
 * 备注: 防软件定时器
 */
static void RLIN31_sta_check(void)
{
    if ( 1 == Get1MsTickInterval(u32LinRecTick,LIN_TIMEOUT))
    {
        Lin_Tick_Update();
        if (RLINSTA_NORMAL == RLIN31_sta_get())
        {
            RLIN31_sta_update(RLINSTA_SLEEP);
        }
    }
}

/* 
 * 函数介绍: lin31 main task
 * 返回值: {*}
 * 备注: 
 */
void lin31_main(void)
{
    RLIN31_sta_check();
}
#endif
/*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑应用层函数定义结束↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/